/**
 * 
 */
package ej.ea;

import java.util.EnumMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * USE ENUMMAP INSTEAD OF ORDINAL INDEXING
 * 
 * @author sunaina.sharma
 * 
 */
public class EnumMapVsOrdinalIndexing {

	enum Type {
		ANNUAL, PERENNIAL, BIENNIAL
	}

	class Herb {
		private final String name;
		private final Type type;

		Herb(String name, Type type) {
			this.name = name;
			this.type = type;
		}

		@Override
		public String toString() {
			return name;
		}
	}

	// Using a nested EnumMap to associate data with enum pairs
	public enum Phase {
		SOLID, LIQUID, GAS;
		public enum Transition {
			MELT(SOLID, LIQUID), FREEZE(LIQUID, SOLID), BOIL(LIQUID, GAS), CONDENSE(
					GAS, LIQUID), SUBLIME(SOLID, GAS), DEPOSIT(GAS, SOLID);
			final Phase src;
			final Phase dst;

			Transition(Phase src, Phase dst) {
				this.src = src;
				this.dst = dst;
			}

			// Initialize the phase transition map
			private static final Map<Phase, Map<Phase, Transition>> m = new EnumMap<Phase, Map<Phase, Transition>>(
					Phase.class);
			static {
				for (Phase p : Phase.values())
					m.put(p, new EnumMap<Phase, Transition>(Phase.class));
				for (Transition trans : Transition.values())
					m.get(trans.src).put(trans.dst, trans);
			}

			public static Transition from(Phase src, Phase dst) {
				return m.get(src).get(dst);
			}
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		Herb[] garden = new Herb[3];

		/*
		 * Using an EnumMap to associate data with an enum.that EnumMap is
		 * comparable in speed to an ordinal-indexed array is that EnumMap uses
		 * such an array internally. But it hides this implementation detail
		 * from the programmer, combining the richness and type safety of a Map
		 * with the speed of an array.
		 */

		// EnumMap constructor takes the Class object of the key type: this
		// is a bounded type token, which provides runtime generic type
		// information
		Map<Type, Set<Herb>> herbsByType = new EnumMap<Type, Set<Herb>>(
				Type.class);
		for (Type t : Type.values())
			herbsByType.put(t, new HashSet<Herb>());
		for (Herb h : garden)
			herbsByType.get(h.type).add(h);
		System.out.println(herbsByType);
	}
}
